home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / smphone / ph2mm_send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-11  |  13.5 KB  |  609 lines

  1. #include "util.h"
  2. #include "mmdf.h"
  3.  
  4. /*
  5.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  6.  *     
  7.  *
  8.  *     Copyright (C) 1979,1980,1981  University of Delaware
  9.  *     
  10.  *     Department of Electrical Engineering
  11.  *     University of Delaware
  12.  *     Newark, Delaware  19711
  13.  *
  14.  *     Phone:  (302) 738-1163
  15.  *     
  16.  *     
  17.  *     This program module was developed as part of the University
  18.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  19.  *     
  20.  *     Acquisition, use, and distribution of this module and its listings
  21.  *     are subject restricted to the terms of a license agreement.
  22.  *     Documents describing systems using this module must cite its source.
  23.  *
  24.  *     The above statements must be retained with all copies of this
  25.  *     program and may not be removed without the consent of the
  26.  *     University of Delaware.
  27.  *     
  28.  *
  29.  *     version  -1    David H. Crocker    March   1979
  30.  *     version   0    David H. Crocker    April   1980
  31.  *     version  v7    David H. Crocker    May     1981
  32.  *     version   1    David H. Crocker    October 1981
  33.  *
  34.  */
  35. /*                  SEND FROM PHONE TO LOCAL (SUBMIT)                   */
  36.  
  37. #include "ch.h"
  38. #include "phs.h"
  39. #include "ph.h"
  40.  
  41. extern char *getline();
  42. extern char *index();
  43. extern char *rindex();
  44. extern char *malloc();
  45.  
  46. char *sender = 0;            /* address of mail sender */
  47.  
  48. #define BUFL 600        /* length of buf */
  49. char    buf[BUFL];        /* general usage */
  50. char    netbuf[BUFL];        /* the place that has the valid characters */
  51. int    netcount = 0;        /* number of valid characters in netbuf */
  52. char    *netptr  = netbuf;    /* next character to come out of netbuf */
  53. char    *arg;            /* zero if no argument - pts to comm param */
  54. int    numrecipients = 0;    /* number of valid recipients accepted */
  55. char    *addrfix();
  56. int     doneflag = 0;
  57.  
  58. /* character defines */
  59. #define CNULL    '\0'    /* null */
  60.  
  61.  
  62. /****************************************************************
  63.  *                                                              *
  64.  *      C O M M A N D   D I S P A T C H   T A B L E             *
  65.  *                                                              *
  66.  ****************************************************************/
  67.  
  68. int helo(), mail(), quit(), help(), rcpt(), accept();
  69. int data(), rset(), reject(), turn();
  70.  
  71. struct comarr        /* format of the command table */
  72. {
  73.     char *cmdname;        /* ascii name */
  74.     int (*cmdfunc)();       /* command procedure to call */
  75. } commands[] = {
  76.     "helo", helo,        "noop", accept,
  77.     "mail", mail,        "data", data,
  78.     "rcpt", rcpt,        "help", help,
  79.     "send", mail,        "quit", quit,
  80.     "saml", mail,        "soml", reject,
  81.     "vrfy", reject,        "expn", reject,
  82.     "rset", rset,           "turn", turn,
  83.     NULL, NULL
  84. };
  85.  
  86. extern LLog *logptr;
  87. extern struct ps_rstruct ps_rp;
  88. extern char *supportaddr;
  89. extern Chan *curchan;
  90.  
  91. LOCVAR long msglen;
  92. LOCVAR int numadrs;
  93.  
  94. ph2mm_send (curchan)             /* overall mngmt for batch of msgs    */
  95.     Chan *curchan;               /* who to say is doing relaying       */
  96. {
  97.     short     result;
  98.     char *i;
  99.     char    info[LINESIZE],
  100.             sender[LINESIZE];
  101.     register struct comarr *comp;
  102.  
  103. #ifdef DEBUG
  104.     ll_log (logptr, LLOGPTR, "ph2mm_send");
  105. #endif
  106.  
  107.     if (rp_isbad (result = ph_pkinit ()))
  108.     {
  109.     printx ("remote site refuses to send mail...\n");
  110.     fflush (stdout);
  111.     return (result);
  112.     }
  113.     if (rp_isbad (result = mm_sbinit ()))
  114.     return (result);
  115.  
  116.     printx ("starting to pickup mail...\n");
  117.     fflush (stdout);
  118.  
  119. nextcomm:
  120.     while (i = getline())
  121.     {
  122.         if (i == (char *)NOTOK)        /* handle error ??? */
  123.             return(byebye( 1 ));
  124.  
  125.         /* find and call command procedure */
  126.         comp = commands;
  127.         while( comp->cmdname != NULL)    /* while there are names */
  128.         {
  129.             if (strcmp(buf, comp->cmdname) == 0) /* a winner */
  130.             {
  131.             /* call comm proc */
  132.             result = (*comp->cmdfunc)();
  133.             if (doneflag)           /* set by byebye */
  134.                 return(result);
  135.             goto nextcomm;        /* back for more */
  136.             }
  137.             comp++;        /* bump to next candidate */
  138.         }
  139.         netreply("500 I never heard of that command before" );
  140.     }
  141.     return(byebye(0));
  142. }
  143.  
  144. /*name:
  145.     getline
  146.  
  147. function:
  148.     get commands from the standard input terminated by <cr><lf>.
  149.     afix a pointer( arg ) to any arguments passed.
  150.     ignore carriage returns
  151.     map UPPER case to lower case.
  152.     manage the netptr and netcount variables
  153.  
  154. algorithm:
  155.     while we havent received a line feed and buffer not full
  156.  
  157.         if netcount is zero or less
  158.             get more data from net
  159.                 error: return 0
  160.         check for delimiter character
  161.             null terminate first string
  162.             set arg pointer to next character
  163.         check for carriage return
  164.             ignore it
  165.         if looking at command name
  166.             convert upper case to lower case
  167.  
  168.     if command line (not mail)
  169.         null terminate last token
  170.     manage netptr
  171.  
  172. returns:
  173.     0 for EOF
  174.     -1 when an error occurs on network connection
  175.     ptr to last character (null) in command line
  176.  
  177. globals:
  178.     netcount=
  179.     netptr =
  180.     buf=
  181. */
  182.  
  183. char *
  184. getline()
  185. {
  186.     register char *inp;    /* input pointer in netbuf */
  187.     register char *outp;    /* output pointer in buf */
  188.     register int c;        /* temporary char */
  189.     extern char *progname;
  190.  
  191.     inp = netptr;
  192.     outp = buf;
  193.     arg = 0;
  194.  
  195.     if (rp_isbad (ph_rrec(netbuf, &netcount)))
  196.     {
  197.         ll_log( logptr, LLOGTMP, "net input read error");
  198.         return((char *)NOTOK);
  199.     }
  200.     inp = netbuf;
  201.     do
  202.     {
  203.         c = *inp++ & 0377;
  204.         if (c == '\r' ||    /* ignore CR */
  205.             c >= 0200)        /* or any telnet codes that */
  206.             continue;    /*  try to sneak through */
  207.         if (arg == NULL)
  208.         {
  209.             /* if char is a delim afix token */
  210.             if (c == ' ' || c == ',')
  211.             {
  212.                 c = CNULL;       /* make null term'ed */
  213.                 arg = outp + 1; /* set arg ptr */
  214.             }
  215.             else if (c >= 'A' && c <= 'Z')
  216.             /* do case mapping (UPPER -> lower) */
  217.                 c += 'a' - 'A';
  218.         }
  219.         *outp++ = c;
  220.     } while (netcount-- > 0 && outp < &buf[BUFL] );
  221.  
  222.     *--outp = 0;                    /* null term the last token */
  223.  
  224.     /* scan off blanks in argument */
  225.     if (arg) {
  226.         while (*arg == ' ')
  227.             arg++;
  228.         if (*arg == '\0')
  229.             arg = 0;    /* if all blanks, no argument */
  230.     }
  231.     ll_log( logptr, LLOGFTR, "'%s', '%s'", buf, 
  232.                     arg == 0 ? "<noarg>" : arg );
  233.  
  234.     /* reset netptr for next trip in */
  235.     netptr = inp;
  236.     /* return success */
  237.     return (outp);
  238. }
  239.  
  240. /*
  241.  *  Process the HELO command
  242.  */
  243. helo()
  244. {
  245.     char replybuf[128];
  246.  
  247.     if (curchan -> ch_confstr)
  248.         sprintf (replybuf, "250 %s", curchan -> ch_confstr);
  249.     else
  250.         sprintf (replybuf, "250 %s.%s", curchan -> ch_lname,
  251.                             curchan -> ch_ldomain);
  252.     netreply (replybuf);
  253. }
  254.  
  255. /*
  256.  *    mail
  257.  *
  258.  *    handle the MAIL command  ("MAIL from:<user@host>")
  259.  */
  260. mail()
  261. {
  262.     int result;
  263.     char    *cp;
  264.     char    info[40];
  265.     char    replybuf[256];
  266.     struct    rp_bufstruct thereply;
  267.     int    len;
  268.  
  269.     if (arg == 0) {
  270.         netreply("501 No argument supplied");
  271.         return;
  272.     } else if( sender ) {
  273.         netreply("503 MAIL command already accepted");
  274.         return;
  275.     } else if (!equal(arg, "from:", 5)) {
  276.         netreply("501 No sender named");
  277.         return;
  278.     }
  279.  
  280.     if (equal(buf, "mail", 4))
  281.         strcpy (info, "mv");
  282.     else if (equal(buf, "send", 4))
  283.         strcpy (info, "yv");
  284.     else if (equal(buf, "saml", 4))
  285.         strcpy (info, "bv");
  286.     else
  287.         strcpy (info, "mv");  /* shouldn't ever get here */
  288.  
  289.     /* Scan FROM: parts of arg */
  290.     sender = index (arg, ':') + 1;
  291.     sender = addrfix( sender );
  292.  
  293.     /* Supply necessary flags, "tiCHANNEL" will be supplied by winit */
  294.     if (*sender == NULL) {
  295.         strcat( info, "q");         /* No return mail */
  296.         sender = "Orphanage";        /* Placeholder */
  297.     } 
  298.  
  299.     if( rp_isbad( mm_winit(curchan -> ch_name, info, sender))) {
  300.         netreply("451 Temporary problem initializing");
  301.         sender = (char *) 0;
  302.         mm_end( NOTOK );
  303.         mmdfstart();
  304.     } else if( rp_isbad( mm_rrply( &thereply, &len ))) {
  305.         netreply( "451 Temporary problem initializing" );
  306.         sender = (char *) 0;
  307.         mm_end( NOTOK );
  308.         mmdfstart();
  309.     } else if( rp_gbval( thereply.rp_val ) == RP_BNO) {
  310.         sprintf (replybuf, "501 %s", thereply.rp_line);
  311.         netreply (replybuf);
  312.         sender = (char *) 0;
  313.         mm_end( NOTOK );
  314.         mmdfstart();
  315.     } else if( rp_gbval( thereply.rp_val ) == RP_BTNO) {
  316.         sprintf (replybuf, "451 %s", thereply.rp_line);
  317.         netreply (replybuf);
  318.         sender = (char *) 0;
  319.         mm_end( NOTOK );
  320.         mmdfstart();
  321.     } else
  322.         netreply("250 OK");
  323.     numrecipients = 0;
  324. }
  325.  
  326. /*
  327.  *  Process the RCPT command  ("RCPT TO:<forward-path>")
  328.  */
  329. rcpt()
  330. {
  331.     register char *p;
  332.     struct rp_bufstruct thereply;
  333.     char    replybuf[256];
  334.     int    len;
  335.  
  336.     /* parse destination arg */
  337.     if( sender == (char *)0 ) {
  338.         netreply("503 You must give a MAIL command first");
  339.         return;
  340.     } else if (arg == (char *)0 || !equal(arg, "to:", 3)) {
  341.         netreply("501 No recipient named.");
  342.         return;
  343.     }
  344.     p = index( arg, ':' ) + 1;
  345.     p = addrfix( p );
  346.  
  347.     if( rp_isbad( mm_wadr( (char *)0, p ))) {
  348.         if( rp_isbad( mm_rrply( &thereply, &len )))
  349.             netreply( "451 Mail system problem" );
  350.         else {
  351.             sprintf (replybuf, "451 %s", thereply.rp_line);
  352.             netreply (replybuf);
  353.         }
  354.     } else {
  355.         if( rp_isbad( mm_rrply( &thereply, &len )))
  356.             netreply("451 Mail system problem");
  357.         else if( rp_gbval( thereply.rp_val ) == RP_BNO) {
  358.             sprintf (replybuf, "550 %s", thereply.rp_line);
  359.             netreply (replybuf);
  360.         }
  361.         else if( rp_gbval( thereply.rp_val ) == RP_BTNO) {
  362.             sprintf (replybuf, "451 %s", thereply.rp_line);
  363.             netreply (replybuf);
  364.         }
  365.         else {
  366.             netreply("250 Recipient OK.");
  367.             numrecipients++;
  368.         }
  369.     }
  370. }
  371.  
  372. /*
  373.  *    ADDRFIX()  --  This function takes the SMTP "path" and removes
  374.  *    the leading and trailing "<>"'s which would make the address
  375.  *    illegal to RFC822 mailers.  Note that although the spec states
  376.  *    that the angle brackets are required, we will accept addresses
  377.  *    without them.   (DPK@BRL, 4 Jan 83)
  378.  */
  379. char *
  380. addrfix( addrp )
  381. char *addrp;
  382. {
  383.     register char    *cp;
  384.  
  385.     if( cp = index( addrp, '<' )) {
  386.         addrp = ++cp;
  387.         if( cp = rindex( addrp, '>' ))
  388.             *cp = 0;
  389.     }
  390.     compress (addrp, addrp);
  391. #ifdef DEBUG
  392.     ll_log( logptr, LLOGFTR, "addrfix(): '%s'", addrp );
  393. #endif
  394.     return( addrp );
  395. }
  396.  
  397. /*
  398.  *  Process the DATA command.  Send text to MMDF.
  399.  */
  400. data()
  401. {
  402.     int    werrflg;
  403.     struct rp_bufstruct thereply;
  404.     int    len;
  405.     int     result;
  406.  
  407.     werrflg = 0;
  408.     if (numrecipients == 0) {
  409.         netreply("503 No recipients have been specified.");
  410.         return;
  411.     }
  412.  
  413.     if( rp_isbad(mm_waend())) {
  414.         netreply("451 Unknown mail system trouble.");
  415.         return;
  416.     }
  417.  
  418.     netreply ("354 Enter Mail, end by a line with only '.'");
  419.  
  420. #ifdef DEBUG
  421.     ll_log( logptr, LLOGFTR, "... body of message ..." );
  422. #endif
  423.     printx ("receiving...:");
  424.     fflush (stdout);
  425.  
  426.         len = BUFL;
  427.         while ((rp_gval (result = ph_rstm (buf, &len))) == RP_OK)
  428.         {
  429.         printx (".");
  430.         fflush (stdout);
  431.  
  432.         /* If write error occurs, stop writing but keep reading. */
  433.         if (!werrflg)
  434.                 if (rp_isbad (result = mm_wtxt (buf, len))) {
  435.                 werrflg++;
  436.                 ll_log( logptr, LLOGTMP, "error from submit");
  437.             }
  438.  
  439.         len = BUFL;
  440.         }
  441. #ifdef DEBUG
  442.     ll_log( logptr, LLOGBTR, "Finished receiving text." );
  443. #endif
  444.     if (rp_isbad(result)) {
  445.         ll_log (logptr, LLOGTMP, "error reading text");
  446.         printx("\n\terror reading text\n");
  447.         fflush(stdout);
  448.         return(byebye( 1 ));
  449.     }
  450.  
  451.     if (werrflg) {
  452.         netreply("451-Mail trouble (write error to mailsystem)");
  453.         netreply("451 Please try again later.");
  454.         return(byebye( 1 ));
  455.     }
  456.  
  457.     printx(" "); /* keep it pretty */
  458.     fflush(stdout);
  459.  
  460.     /* slurp up the end-of-text dot (we knew we were done anyway) */
  461.     len = BUFL;
  462.     if (rp_isbad(ph_rrec(buf, &len))) {
  463.         ll_log(logptr, LLOGTMP, "error reading '.'");
  464.         printx("\n\terror reading '.'\n");
  465.         fflush(stdout);
  466.         return(byebye( 1 ));
  467.     }
  468.  
  469.     if( rp_isbad(mm_wtend()) || rp_isbad( mm_rrply( &thereply, &len)))
  470.         netreply("451 Unknown mail trouble, try later");
  471.     else if( rp_isgood(thereply.rp_val)) {
  472.         sprintf (buf, "250 %s", thereply.rp_line);
  473.         netreply (buf);
  474.     }
  475.     else if( rp_gbval(thereply.rp_val) == RP_BNO) {
  476.         sprintf (buf, "554 %s", thereply.rp_line);
  477.         netreply (buf);
  478.     }
  479.     else {
  480.         sprintf (buf, "451 %s", thereply.rp_line);
  481.         netreply (buf);
  482.     }
  483.     sender = (char *) 0;
  484.     numrecipients = 0;
  485. }
  486.  
  487. /*
  488.  *  Process the TURN command
  489.  */
  490. turn()
  491. {
  492.     accept();
  493.     return(byebye(3));  /* pass the turn message upstairs */
  494. }
  495.  
  496. /*
  497.  *  Process the RSET command
  498.  */
  499. rset()
  500. {
  501.     mm_end( NOTOK );
  502.     sender = (char *)0;
  503.     mmdfstart();
  504.     accept();
  505. }
  506.  
  507. mmdfstart()
  508. {
  509.     if( rp_isbad( mm_init() ) || rp_isbad( mm_sbinit() )) {
  510.         ll_log( logptr, LLOGFAT, "can't reinitialize mail system" );
  511.         netreply("421 Server can't initialize mail system (mmdf)");
  512.         return(byebye( 2 ));
  513.     }
  514.     numrecipients = 0;
  515. }
  516.  
  517. /*
  518.  *  handle the QUIT command
  519.  */
  520. quit()
  521. {
  522.     char    buf[128];
  523.     time_t    timenow;
  524.  
  525.     time (&timenow);
  526.     sprintf (buf, "221 session complete at %.19s.",
  527.         ctime(&timenow));
  528.     netreply(buf);
  529.     return(byebye( 0 ));
  530. }
  531.  
  532. byebye( retval )
  533. int retval;
  534. {
  535.     doneflag++;
  536.     switch (retval)
  537.     {
  538.         case 0:
  539.         mm_sbend();
  540.         mm_end(OK);
  541.         return(RP_DONE);
  542.         case 1:
  543.         mm_end (NOTOK);
  544.         return (RP_BTNO);
  545.         case 2:       
  546.         mm_end (NOTOK);
  547.         return (RP_NO);
  548.         case 3:
  549.         mm_sbend();
  550.         mm_end(OK);
  551.         return(RP_OK);  /* signal that we should turn line around */
  552.     }
  553. }
  554.  
  555. /*
  556.  *  Reply that the current command has been logged and noted
  557.  */
  558. accept()
  559. {
  560.     netreply("250 OK");
  561. }
  562.  
  563. /*
  564.  *  Tell other side that we don't support a command.
  565.  */
  566. reject()
  567. {
  568.     netreply("502 Command not implemented.");
  569. }
  570.  
  571. /*
  572.  *  Process the HELP command by giving a list of valid commands
  573.  */
  574. help()
  575. {
  576. /*      register i; */
  577. /*      register struct comarr *p; */
  578.     char    replybuf[256];
  579.  
  580. /*      netreply("214-The following commands are accepted:\r\n214-" );
  581.  *      for(p = commands, i = 1; p->cmdname; p++, i++) {
  582.  *          sprintf (replybuf, "%s%s", p->cmdname, ((i%10)?" ":"\r\n214-") );
  583.  *          netreply (replybuf);
  584.  *      }
  585.  */
  586.     sprintf (replybuf, "214 Send complaints/bugs to:  %s", supportaddr);
  587.     netreply (replybuf);
  588. }
  589.  
  590. /*
  591.  *  Send appropriate ascii responses over the network connection.
  592.  */
  593.  
  594. netreply(string)
  595. char *string;
  596. {
  597.     int len;
  598.  
  599.     if (rp_isbad( ph_wrec(string, strlen(string)))) {
  600.         ll_log( logptr, LLOGFST,
  601.             "(netreply) error in writing [%s] ...",
  602.             string);
  603.         return(byebye( 1 ));
  604.     }
  605. #ifdef DEBUG
  606.     ll_log( logptr, LLOGFTR, "%s", string);
  607. #endif DEBUG
  608. }
  609.